/**
 * User: laice
 * Date: 9/27/13
 * Time: 2:42 AM
 */

exports.action_queue = new Array();
exports.monitor_log = new Array();
exports.data_queue = new Array();
exports.paths = {};
exports.current_salt = {};
exports.current_fm_player = {};
exports.current_pm_player = {};
exports.current_peppermill = {};
exports.current_peppermill.p1 = {};
exports.current_peppermill.p2 = {};
exports.wins = {};
exports.wins.p1 = {};
exports.wins.p2 = {};
exports.losses = {};
exports.losses.p1 = {};
exports.losses.p2 = {};
exports.elos = {};
exports.elos.p1 = {};
exports.elos.p1.wins = {};
exports.elos.p1.losses = {};
exports.elos.p2 = {};
exports.elos.p2.wins = {};
exports.elos.p2.losses = {};
exports.name_dictionary = [];
exports.comments = {};
exports.comments.p1 = {};
exports.comments.p2 = {};
exports.win_log = {};
exports.win_log.p1 = {};
exports.win_log.p2 = {};
exports.loss_log = {};
exports.loss_log.p1 = {};
exports.loss_log.p2 = {};
exports.tags = {};
exports.tags.p1 = {};
exports.tags.p2 = {};
exports.prev_salt = {};
exports.salt_logs = new Array();
exports.mrt = new Array();
exports.tails = new Array();
exports.client_sockets = new Array();
exports.client_ids = new Array();
exports.mrt.menu;
exports.mrt.footer;
exports.mrt.header;
exports.mrt.main;
exports.mrt.home;
exports.server_mode;
exports.attributes = {};
exports.paths.host = '';
exports.paths.path = '';
exports.url = exports.paths.host;
exports.path = exports.paths.path;
exports.action_interval = 100;
exports.data_interval = 100;        // read rate millis
exports.if_mod_interval = 5100;     // fetch rate milli
exports.p1_elo_sent = false;
exports.p2_elo_sent = false;
exports.fetched_elo = false;
exports.match_logged = false;


var Server = require('./server.js');


var hasOwnProperty = Object.prototype.hasOwnProperty;

exports.is_empty = function(obj) {

    // null and undefined are empty
    if (obj == null) return true;
    // Assume if it has a length property with a non-zero value
    // that that property is correct.
    if (obj.length && obj.length > 0)    return false;
    if (obj.length === 0)  return true;

    for (var key in obj) {
        if (hasOwnProperty.call(obj, key))    return false;
    }

    // Doesn't handle toString and toValue enumeration bugs in IE < 9

    return true;
}

exports.render = function(callback) {
    var jade = require('jade');
    exports.mrt.menu = jade.renderFile('views/menu.jade');
    exports.mrt.footer = jade.renderFile('views/footer.jade', {time : exports.time_stamp()});
    exports.mrt.header = jade.renderFile('views/header.jade');

    var mode = exports.server_mode;
    if (mode == "current_match") {
        exports.set_main_match();
    } else {
        exports.mrt.main = jade.renderFile('views/main.jade', {posts : exports.mrt.posts, mode : "post"});
    }

    exports.mrt.home = jade.renderFile('views/home.jade', {mrt: exports.mrt});


    if(callback){callback()}
}

exports.request = function( params, callback ) {
    var http = require('http');

    http.get(params, callback)

}

exports.report_res = function(res) {
    var http = require('http');

    //console.log(res.statusCode)
    //console.log("report res path " + res.path);
    //res.end();
   // if(res.statusCode == 200){

        var req_params = {
            host: exports.url,
            path: exports.path,
            method: 'GET',
            headers: {
            }
        }

        http.get(req_params, exports.add_data).on('error', function(e) {if(e) console.log(e);});
   // }  else {
    //    exports.status_code_handler(res);
    //}


}


exports.parse_salty_data = function(data){
    var salt_pat = /\{"p1name":"Player 1","p2name":"Player 2","p1total":"([\d,]+)","p2total":"([\d,]+)","status":"([\d\w]+)","alert":([\d\w]+),"x":([\d\w]+)\}/;
    var salt_result = salt_pat.exec(data);

    if(!exports.is_empty(salt_result)){

            exports.prev_salt.p1total = exports.current_salt.p1total;
            exports.prev_salt.p2total = exports.current_salt.p2total;
            exports.prev_salt.status = exports.current_salt.status;
            exports.prev_salt.alert = exports.current_salt.alert;
            exports.prev_salt.x = exports.current_salt.x;

            exports.current_salt.p1total = salt_result[1];
            exports.current_salt.p2total = salt_result[2];
            exports.current_salt.status = salt_result[3];
            exports.current_salt.alert = salt_result[4];
            exports.current_salt.x = salt_result[5];

            if(exports.prev_salt.status !== exports.current_salt.status) {
                console.log("status change");
                //console.log(salt_result);
                console.log(data);
                // states of the salty bet app
                switch(exports.current_salt.status) {
                    case "open":  // betting open
                        Server.match_status("open");
                        break;
                    case "locked":  // betting closed
                        Server.match_status("locked");
                        break;
                    case "1":   // player 1 wins
                        Server.match_status("1");
                        Server.roundly();
                        break;
                    case "2":  // player 2 wins
                        Server.match_status("2");
                        Server.roundly();
                        break;
                    default:

                        break;
                }

            }


    }
}

exports.cleanup = function() {

    exports.current_salt = null;

}


exports.set_url = function( url ){
    exports.paths.host = url;
    exports.url = exports.paths.host;
}

exports.set_path = function( path ){
    exports.paths.path = path;
    exports.path = exports.paths.path;
}



exports.if_mod_since = function( res ) {

    var if_mod_func = function(res) {
        //console.log(init_res);
        //console.log(res);
        //console.log(exports.url);
        //console.log(init_res.headers.date);
        //var http = require('http');
        var request = require('request');
       // console.log("if mod since path " + res.path);
        /*
        var req_params = {
            host: exports.url,
            path: exports.path,
            method: 'HEAD',
            headers: {
                //'If-Modified-Since': res.headers.date
            }
        } */

        var s = exports.url + exports.path;
        request(s, function(error, res, data){
            if(!error && res.statusCode == 200){
                exports.data_queue.push(data);
            }
        });
        //http.get(req_params, exports.report_res).on('error', function(e){ if(e) throw e;})
    }

    exports.if_mod_interval_id = setInterval(if_mod_func, exports.if_mod_interval, res);
}

exports.monitor_page = function() {
    //console.log("monitor page path " + path);
    var monitor = new Object();
    monitor.url = exports.url;
    monitor.path = exports.path;
    monitor.port = 80;

    exports.monitor_log.push(monitor);
    var http = require('http');
    http.get(monitor, exports.if_mod_since).on('error', function(e){console.log(e);});

}

exports.add_data = function(res) {
    res.setEncoding('utf8');
    res.on('data', function(data){
       exports.data_queue.push(data);
    });
    //res.end();
}

exports.add_action = function(action){
    exports.action_queue.push(action);
}

exports.set_action_interval = function( millisecs ) {
    exports.action_interval = millisecs;
}

exports.set_data_interval = function( millisecs ) {
    exports.data_interval = millisecs;
}

exports.do_action = function(callback){
    if(exports.action_queue.length > 0)
        callback(exports.action_queue.shift());

}

exports.get_data = function(callback){
    if(exports.data_queue.length > 0)
       // console.log(exports.data_queue);
        callback(exports.data_queue.shift());
       // console.log(exports.data_queue);
}

exports.present_data = function(data) {
    if(exports.new_data) exports.prev_data = exports.new_data;
    exports.new_data = data;
}

exports.exec = function(exec){
    exec();
}


exports.status_code_handler = function(res) {
    if(res.statusCode == 304) {
        console.log('304');
        exports.add_action(exports.if_mod_since(res));
    }
}

exports.tail_irc_log = function(log) {

    //var Tail = require('tail').Tail;
    var path = LOG_PATH + log;
    var fs = require('fs');

    fs.watchFile(path, {persistent: true, interval: 3000}, function(curr, prev) {
        fs.readFile(path, {encoding : 'utf8', flag : 'r'}, function(err, data) {
            if(err) console.log(err);

            var lined = data.match(/^.*((\r\n|\n|\r)|$)/gm);

            for(var i = 10; i > 0; i--) {
                var len = lined.length;
                var tail = lined[len-i];
                exports.parse_peppermill(tail);
            }




        });
    });





    /*
    var len = exports.tails.push(new Tail(path));

    console.log(exports.tails[len-1]);

    exports.tails[len-1].on("line", function(data){
        console.log("new log line" + exports.time_stamp());
        exports.parse_peppermill(data);
    });

    exports.tails[len-1].on("error", function(err) { console.log(err);});


    var fs = require('fs');
    var path = LOG_PATH + log;
    var watch_callback = function(curr, prev) {
        var a = 'in callback'
        console.log(curr);
        curr.replace(prev, '');
        console.log(curr);
    }

    fs.watchFile(path, watch_callback);
    */
}

exports.convert_name_id = function(name){

    name = name.toLowerCase();

    console.log("converting name : " + name);

    if (!exports.is_empty(exports.name_dictionary)){
        var a

        if(exports.is_empty(exports.name_dictionary[name]))
            var a = "'" + name + "'";
        else
            var a = name;


        console.log("id is : " + exports.name_dictionary[name]);
        return exports.name_dictionary[name];
    }

}



exports.get_name_dictionary = function(){

    var request = require('request')

    var s = "http://apeppershaker.com/api/champions/list";

    request(s, function(error, res, body){
        if(!error && res.statusCode == 200){
            //console.log(body);
            exports.name_dictionary = JSON.parse(body);
            console.log(exports.name_dictionary);
        }
    });



    /*
    var http = require('http');

    var s = "http://apeppershaker.com/api/champions/list";

    http.get(s, function(res){
        res.setEncoding('utf8');

        res.on('data', function(data){

            var is_full = data.substring(data.length-1);
            var full_string = "";

            if(is_full != "}") {
                console.log("fragmented name dictionary, patching.. ");
                name_dic_first.push(data);
                //console.log(data);
            }   else {
                if(!exports.is_empty(name_dic_first)){
                    for(var i in name_dic_first){
                        full_string = full_string + name_dic_first[i-1];
                    }
                }   else {
                    full_string = data;
                }
            }

            if(!exports.is_empty(full_string)) {
                console.log(full_string);
                exports.name_dictionary = JSON.parse(full_string);
                console.log("got name dictionary");
            }


        });

    });

     */


}

exports.add_elo = function(elo, player, pos){

    console.log('adding elo: ' + elo + ' to player ' + player + ' pos ' + pos);
    if(player == 1){
        if(pos == "win"){
            var len = exports.elos.p1.wins.length;
            exports.elos.p1.wins[len] = elo;
            if(len == exports.current_peppermill.p1.wins){
                console.log('end of p1 wins');
            }

        } else if( pos == "loss" ){
            var len = exports.elos.p1.losses.length;
            exports.elos.p1.losses[len] = elo;
            if(len == exports.current_peppermill.p1.losses){
                console.log('end of p1 losses');
            }
            //for(var i in exports.elos.p1.losses) console.log("p1 ll: " + exports.elos.p1.losses[i]);
        }
    } else if(player == 2){
        if(pos == "win"){
            var len = exports.elos.p2.wins.length;
            exports.elos.p2.wins[len] = elo;
            if(len == exports.current_peppermill.p2.wins){
                console.log('end of p2 wins');
            }
        } else if( pos == "loss" ){
            var len = exports.elos.p2.losses.length;
            exports.elos.p2.losses[len] = elo;
            if(len == exports.current_peppermill.p2.losses){
                console.log('end of p2 losses');
            }
        }
    }
}

exports.get_fought_elo = function(ids, player, pos){

    var request = require('request');
    for(var i in ids){

        var id = ids[i];
        console.log("getting id elo: " + id)
        var s = "http://www.apeppershaker.com/api/champions/" + id;
        request(s, function(error, res, data){
            if(error)console.log(error);

            if(res.statusCode !== 200) console.log('status code not 200: ' + res.statusCode + " data: " + data);

            if(!error && res.statusCode == 200) {
                //console.log("fight elo data : " + data);

                var p = JSON.parse(data);

                exports.add_elo(p.elo, player, pos)


            }
        });
    }
}


/*
exports.get_fought_elo = function(list, player, pos){

    var request = require('request');
    for(var i in list){

        var id = exports.convert_name_id(list[i]);
        var s = "http://www.apeppershaker.com/api/champions/" + id;
        request(s, function(error, res, data){
            if(!error && res.statusCode == 200) {
                //console.log("fight elo data : " + data);

                var p = JSON.parse(data);

                exports.add_elo(p.elo, player, pos)


            }
        });
    }
}*/

exports.parse_heroku_app = function(data) {

    if(!exports.is_empty(data.comments_p1)){
        console.log("comments p1 found");
        exports.comments.p1 = data.comments_p1;
    } else {
        exports.comments.p1 = null;
    }

    if(!exports.is_empty(data.loss_p1)){
        console.log("loss p1 found");
        exports.loss_log.p1 = data.loss_p1;
        //exports.get_fought_elo(data.loss_p1, 1, "loss");
    } else {
        exports.loss_log.p1 = null;
    }

    if(!exports.is_empty(data.win_p1)){
        console.log("win p1 found");
        exports.win_log.p1 = data.win_p1;
       // exports.get_fought_elo(data.win_p1, 1, "win");
    } else {
        exports.win_log.p1 = null;
    }

    if(!exports.is_empty(data.comments_p2)){
        console.log("comments p2 found");
        exports.comments.p2 = data.comments_p2;
    } else {
        exports.comments.p2 = null;
    }

    if(!exports.is_empty(data.loss_p2)){
        console.log("loss p2 found");
        exports.loss_log.p2 = data.loss_p2;
        //exports.get_fought_elo(data.loss_p2, 2, "loss");
    } else {
        exports.loss_log.p2 = null;
    }

    if(!exports.is_empty(data.win_p2)){
        console.log("win p2 found");
        exports.win_log.p2 = data.win_p2;
        //exports.get_fought_elo(data.win_p2, 2, "win");
    } else {
        exports.win_log.p2 = null;
    }

    if(!exports.is_empty(data.tags_p1)){
        console.log('tags p1 found');
        exports.tags.p1 = data.tags_p1;
    } else {
        exports.tags.p1 = null;
    }

    if(!exports.is_empty(data.tags_p2)){
        console.log('tags p2 found');
        exports.tags.p2 = data.tags_p2;
    } else {
        exports.tags.p2 = null;
    }

    Server.log_match();

}

exports.parse_fight_json = function(data) {
    var pat = /\{"(left)":\{"id":(\d+),"name":"(.+)","elo":(\d+),"wins":(\d+),"losses":(\d+),"aggression_index":([\d\w]+),"total_bets":(\d+),"created_at":"(.+)","updated_at":"(.+)","gets_hitboxed":([\d\w]+),"undersized_hitbox":([\d\w]+),"oversized_hitbox":([\d\w]+),"zoning":([\d\w]+),"rushdown":([\d\w]+),"one_hit_knockout":([\d\w]+),"doesnt_super":([\d\w]+),"high_health":([\d\w]+),"low_health":([\d\w]+),"high_damage":([\d\w]+),"low_damage":([\d\w]+),"grappler":([\d\w]+),"grapple_immune":([\d\w]+),"flies":([\d\w]+),"heals":([\d\w]+),"timescammer":([\d\w]+),"has_fakes":([\d\w]+),"bad_ai":([\d\w]+)\},"(right)":\{"id":(\d+),"name":"(.+)","elo":(\d+),"wins":(\d+),"losses":(\d+),"aggression_index":([\d\w]+),"total_bets":(\d+),"created_at":"(.+)","updated_at":"(.+)","gets_hitboxed":([\d\w]+),"undersized_hitbox":([\d\w]+),"oversized_hitbox":([\d\w]+),"zoning":([\d\w]+),"rushdown":([\d\w]+),"one_hit_knockout":([\d\w]+),"doesnt_super":([\d\w]+),"high_health":([\d\w]+),"low_health":([\d\w]+),"high_damage":([\d\w]+),"low_damage":([\d\w]+),"grappler":([\d\w]+),"grapple_immune":([\d\w]+),"flies":([\d\w]+),"heals":([\d\w]+),"timescammer":([\d\w]+),"has_fakes":([\d\w]+),"bad_ai":([\d\w]+)\}\}/;
    var p = pat.exec(data);

    if(!exports.is_empty(p)){
        exports.attributes.p1 = {
            id : p[2],
            elo : p[4],
            aggression_index : p[7],
            total_bets : p[8],
            created : p[9],
            updated : p[10],
            gets_hitboxed : p[11],
            undersized_hitbox : p[12],
            oversized_hitbox : p[13],
            zoning: p[14],
            rushdown: p[15],
            one_hit_knockout: p[16],
            doesnt_super: p[17],
            high_health: p[18],
            low_health: p[19],
            high_damage: p[20],
            low_damage: p[21],
            grappler: p[22],
            grapple_immune: p[23],
            flies: p[24],
            heals: p[25],
            timescammer: p[26],
            has_fakes: p[27],
            bad_ai: p[28]
        }

        exports.attributes.p2 = {
            id : p[30],
            elo : p[32],
            aggression_index : p[35],
            total_bets : p[36],
            created_at : p[37],
            updated_at : p[38],
            gets_hitboxed : p[39],
            undersized_hitbox : p[40],
            oversized_hitbox : p[41],
            zoning: p[42],
            rushdown: p[43],
            one_hit_knockout: p[44],
            doesnt_super: p[45],
            high_health: p[46],
            low_health: p[47],
            high_damage: p[48],
            low_damage: p[49],
            grappler: p[50],
            grapple_immune: p[51],
            flies: p[52],
            heals: p[53],
            timescammer: p[54],
            has_fakes: p[55],
            bad_ai: p[56]
        }
    }

}

exports.parse_peppermill = function(data) {

    var m_pat = /\u005b(\d\d:\d\d)\u005d\s\u003cPeppermill\u003e\s(.*):\s\u005bE:\s([\d\u002d]+)\u005d\s\u005b(\d+)W\u002f(\d+)L\u005d\s\u0028([\d\u002e]+)\u0025\sout\sof\s(\d+)\u0029\s\u007c\s(.*):\s\u005bE:\s([\d\u002d]+)\u005d\s\u005b(\d+)W\u002f(\d+)L\u005d\s\u0028([\d\u002e]+)\u0025\sout\sof\s(\d+)\u0029\s\u007c\sHT:\shttp:\/\/apeppershaker\.com\/api\/f\/(\d+)\/(\d+)/;
    var a = m_pat.exec(data);
    //console.log("in peppermill" + data)
    if(!exports.is_empty(a)) {
        console.log("found match");
        exports.current_peppermill.time = a[1];

        exports.current_peppermill.p1.name = a[2];
        exports.current_peppermill.p1.e = a[3];
        exports.current_peppermill.p1.wins = a[4];
        exports.current_peppermill.p1.losses = a[5];
        exports.current_peppermill.p1.percent = a[6];
        exports.current_peppermill.p1.total_matches = a[7];
        exports.current_peppermill.p1.id = a[14];

        exports.current_peppermill.p2.name = a[8];
        exports.current_peppermill.p2.e = a[9];
        exports.current_peppermill.p2.wins = a[10];
        exports.current_peppermill.p2.losses = a[11];
        exports.current_peppermill.p2.percent = a[12];
        exports.current_peppermill.p2.total_matches = a[13];
        exports.current_peppermill.p2.id = a[15];

        exports.render();

        var mode = Server.get_server_mode();
        console.log("infop parse peppermill" + exports.current_peppermill.p1);
        console.log("infop parse peppermill" + exports.current_peppermill.p2);
        if(exports.fetched_elo == false) {
            Server.get_player_wins(a[14], 1);
            Server.get_player_losses(a[14], 1);
            Server.get_player_wins(a[15], 2);
            Server.get_player_losses(a[15], 2);
            exports.fetched_elo = true;
        }

        if( mode == 'current_match' ){
            Server.teaser_match();
        }

    }
}

exports.set_main_match = function() {
    var jade = require('jade');



    var pep = jade.renderFile('views/player_teaser.jade');

    var new_main = jade.renderFile('views/main.jade',
        {match : pep, mode : "current_match"});

    // find a better way to do this:
    // some way to instigate a refresh serverside?
    exports.mrt.main = new_main;
}

exports.find_salt_logs = function() {
    var fs = require('fs');
    var examine_logs = function(err, results) {
        if(err)console.log(err);

        for(var i in results){
            var res = results[i].indexOf("#salty");
            if(res !== -1) {
                exports.salt_logs.push(results[i]);
                exports.tail_irc_log(results[i]);
            }
        }
    }

    fs.readdir(LOG_PATH, examine_logs)
}



exports.update_css = function(callback) {
    var fs = require('fs');
    var less = require('less');

        fs.readFile('./public/styles.less', { encoding: 'utf8'}, function (err, lcss) {
            if(err) throw err;
            less.render(lcss, function( e, css) {
                if (e) { throw e; }
                //console.log("rendering less" + css);
                fs.writeFile('./public/style.css', css, null, function(err) { if(err) throw err;
                    //console.log("css saved");
                    if(!exports.is_empty(callback)) callback();
                })
            })

        });

}

exports.assign_css = function(template, css) {
    template.css = css;
}


/**
 * Return a timestamp with the format "m/d/yy h:MM:ss TT"
 * @type {Date}
 */

exports.time_stamp = function() {
// Create a date object with the current time
    var now = new Date();

// Create an array with the current month, day and time
    var date = [ now.getMonth() + 1, now.getDate(), now.getFullYear() ];

// Create an array with the current hour, minute and second
    var time = [ now.getHours(), now.getMinutes(), now.getSeconds() ];

// Determine AM or PM suffix based on the hour
    var suffix = ( time[0] < 12 ) ? "AM" : "PM";

// Convert hour from military time
    time[0] = ( time[0] < 12 ) ? time[0] : time[0] - 12;

// If hour is 0, set it to 12
    time[0] = time[0] || 12;

// If seconds and minutes are less than 10, add a zero
    for ( var i = 1; i < 3; i++ ) {
        if ( time[i] < 10 ) {
            time[i] = "0" + time[i];
        }
    }

// Return the formatted string
    return date.join("/") + " " + time.join(":") + " " + suffix;
}











